package com.bjc.base.utils;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class JsCalculate {
	public static void main(String[] args) {
		String str = "-0.2  +(-2*2-20 /5)+7*(-2)=";
		
		// 处理表达式，改为标准表达式
		str = CalculatorUtils.change2StandardFormat(str);
		if(null == str){
			return;
		}

		// 拆分字符和数字
		String[] nums = str.split("[^.0-9]");
		List<Double> numLst = new ArrayList<Double>();
		for (int i = 0; i < nums.length; i++) {
			if (!"".equals(nums[i])) {
				numLst.add(Double.parseDouble(nums[i]));
			}
		}
		
		String symStr = str.replaceAll("[.0-9]", "");
		
		System.out.println(doCalculate(symStr, numLst));
	}
	
	public static Double formatExpression(String symStr) {
		// 处理表达式，改为标准表达式
		symStr = CalculatorUtils.change2StandardFormat(symStr);
		if(null == symStr){
			return -1d;
		}
		// 拆分字符和数字
		String[] nums = symStr.split("[^.0-9]");
		List<Double> numLst = new ArrayList<Double>();
		for (int i = 0; i < nums.length; i++) {
			if (!"".equals(nums[i])) {
				numLst.add(Double.parseDouble(nums[i]));
			}
		}
		symStr = symStr.replaceAll("[.0-9]", "");
		return doCalculate(symStr, numLst);
	}
	
	/**
	 * 
	 * @Title: doCalculate
	 * @Desc: 计算
	 * 
	 * @param symStr符号串
	 * @param numLst数字集合
	 * @return 计算结果
	 * 
	 */
	public static Double doCalculate(String symStr, List<Double> numLst) {
		LinkedList<Character> symStack = new LinkedList<>();// 符号栈
		LinkedList<Double> numStack = new LinkedList<>();// 数字栈
		int i = 0;// numLst的标志位
		int j = 0;// symStr的标志位
		char sym;// 符号
		double num1, num2;// 符号前后两个数
		while (symStack.isEmpty()
				|| !(symStack.getLast() == '=' && symStr.charAt(j) == '=')) {// 形如：
																				// =8=
																				// 则退出循环，结果为8
			if (symStack.isEmpty()) {
				symStack.add('=');
				numStack.add(numLst.get(i++));
			}
			if (CalculatorUtils.symLvMap.get(symStr.charAt(j)) > CalculatorUtils.symLvMap
					.get(symStack.getLast())) {// 比较符号优先级，若当前符号优先级大于前一个则压栈
				if (symStr.charAt(j) == '(') {
					symStack.add(symStr.charAt(j++));
					continue;
				}
				numStack.add(numLst.get(i++));
				symStack.add(symStr.charAt(j++));
			} else {// 当前符号优先级小于等于前一个 符号的优先级
				if (symStr.charAt(j) == ')' && symStack.getLast() == '(') {// 若（）之间没有符号，则“（”出栈
					j++;
					symStack.removeLast();
					continue;
				}
				if (symStack.getLast() == '(') {// “（”直接压栈
					numStack.add(numLst.get(i++));
					symStack.add(symStr.charAt(j++));
					continue;
				}
				num2 = numStack.removeLast();
				num1 = numStack.removeLast();
				sym = symStack.removeLast();
				switch (sym) {
				case '+':
					numStack.add(CalculatorUtils.plus(num1, num2));
					break;
				case '-':
					numStack.add(CalculatorUtils.reduce(num1, num2));
					break;
				case '*':
					numStack.add(CalculatorUtils.multiply(num1, num2));
					break;
				case '/':
					if (num2 == 0) {// 除数为0
						System.out.println("存在除数为0");
						return null;
					}
					numStack.add(CalculatorUtils.divide(num1, num2));
					break;
				}
			}
		}
		return numStack.removeLast();
	}
}
